package com.zbl.小题大做;

/*
- &：与，同位都为1取1，否则取0。全为1才为1
- |：或，同位有1取1，都为0取0。有1就成
- ^：异或，同位不同取1，相同取0。无进位加法，简单理解位加法，但是不会进位
- ~：取反，同位取反
- <<：带符号左移，左值 * （2的右值次方）
- `>>`：带符号右移，左值 / （2的右值次方）
- `>>>`：无符号右移，左值 / （2的右值次方），正数：同`>>`；负数：把符号位带入运算，空位补0
 */
public class 位运算 {
    public static void main(String[] args) {
        System.out.println(-8 >> 2);
    }

    // 打印二进制
    public static void printBinary(int num) {
        for (int i = 31; i >= 0; i--) {
            System.out.print(((num >> i) & 1) == 0 ? 0 + " " : 1 + " ");
        }
        System.out.println();
    }

    // 无中间变量交换两个值
    public static void changeAB(int a, int b) {
        System.out.println("a=" + a + " b=" + b);
        //a = a + b;
        //b = a - b;
        //a = a - b;
        a = a ^ b;
        b = a ^ b;
        a = a ^ b;
        System.out.println("a=" + a + " b=" + b);
    }

    // 寻找二进制首个1
    public static void findFirst1(int  num) {
        printBinary(num);
        //printBinary(num & (~num + 1));
        printBinary(num & (-num));
    }

    //  打印奇数。所有数都是偶数次出现，只有一个数是奇数次
    public static void printOddTimesNum(int[] arr) {
        int eor = 0;
        for (int j : arr) {
            eor ^= j;
        }
        System.out.println(eor);
    }

    //  打印奇数。所有数都是偶数次出现，只有两个数是奇数次
    public static void printOddTimesNum2(int[] arr) {
        int eor = 0;
        for (int i : arr) {
            eor ^= i;
        }
        eor = eor & (-eor);// 两数异或值为1的最小位，用以区分两个数（异或运算时，不同才为1）

        int a = 0;
        for (int i : arr) {
            if ((i & eor) == 0) {
                a ^= i;
            }
        }

        System.out.println(a + " 和 " + (a ^ eor));
    }
}
